package com.hyt.it.ogt.kq.common.exception;

import java.util.List;
import java.util.stream.Collectors;

import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import com.hyt.common.apiInfor.ApiResponse;
import com.hyt.core.exception.CheckException;
import com.hyt.exception.exception.BusinessLogicException;
import com.hyt.exception.exception.BusinessRequestException;
import com.hyt.it.ogt.kq.common.config.exception.KqException;
import com.hyt.it.ogt.kq.common.gov.constant.ResponseCode;

import lombok.extern.slf4j.Slf4j;

/**
 * 全局异常统一响应处理
 *
 * @author wangrl
 * @since 2021-09-03
 */

@ControllerAdvice
@Slf4j
@ResponseBody
public class GlobalExceptionHandler {

    @ExceptionHandler(com.hyt.exception.exception.InvalidRequestException.class)
    @ResponseBody
    public ApiResponse<String> error(com.hyt.exception.exception.InvalidRequestException e) {
        if (log.isDebugEnabled()) {
            log.debug("# 全局异常InvalidRequestException处理，code：{}", e.getCode(), e);
        }
        if (log.isErrorEnabled()) {
            log.error("# 全局异常InvalidRequestException处理，code：{}，message：{}", e.getCode(), e.getMessage());
        }
        return e.response();
    }

    @ExceptionHandler(BusinessLogicException.class)
    @ResponseBody
    public ApiResponse<String> error(BusinessLogicException e) {
        if (log.isDebugEnabled()) {
            log.debug("# 全局异常BusinessLogicException处理，code：{}", e.getCode(), e);
        }
        if (log.isErrorEnabled()) {
            log.error("# 全局异常BusinessLogicException处理，code：{}，message：{}", e.getCode(), e.getMsg());
        }
        return e.response();
    }

    @ExceptionHandler(BusinessRequestException.class)
    @ResponseBody
    public ApiResponse<String> error(BusinessRequestException e) {
        return e.response();
    }

    @ExceptionHandler(Exception.class)
    public ApiResponse<?> customException(Exception e) {
        if (log.isDebugEnabled()) {
            log.error("全局异常捕获抛出：{}", e.getMessage(), e);
        }
        //1.参数验证异常1
        if (e instanceof BindException) {
            BindException bindException = (BindException) e;
            return this.validParamException(bindException.getAllErrors());

            //2.requestBody 参数验证异常
        } else if (e instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException methodArgumentNotValidException = (MethodArgumentNotValidException) e;
            return this.validParamException(methodArgumentNotValidException.getBindingResult().getAllErrors());

            //3.参数验证异常2
        } else if (e instanceof KqException) {
            KqException ke = (KqException) e;
            return ApiResponse.builder()
                    .code(ke.getErrCode())
                    .build();
            //4.参数验证异常
        } else if (e instanceof GovInvalidRequestException) {
            GovInvalidRequestException invalid = (GovInvalidRequestException) e;
            return ApiResponse.builder()
                    .code(invalid.getCode())
                    .build();
            //5. 规则校验异常
        } else if (e instanceof CheckException) {
            CheckException checkException = (CheckException) e;
            return ApiResponse.builder()
                    .code(checkException.getCode())
                    .build();
        } else {
            //目前没有找到合适的状态码 ，待完善
            log.info("请求异常{}:{}", ResponseCode.GLOBAL_EXCEPTION_UNKNOWN.getCode(), e);
            return ApiResponse.builder()
                    .code(ResponseCode.GLOBAL_EXCEPTION_UNKNOWN.getCode())
                    .build();
        }

    }

    /**
     * 参数异常统一处理分装
     *
     * @param errors
     * @return
     */
    public ApiResponse<?> validParamException(List<ObjectError> errors) {
        //拼接所有入参错误项
        String msg = errors.stream().map(ObjectError::getDefaultMessage).
                collect(Collectors.joining(","));
        return ApiResponse.builder()
                .code(ResponseCode.COMMON_PARAM_INVALID.getCode())
                .data(msg)
                .build();
    }

}
